package com.wa.config;
import cn.hutool.core.convert.Convert;
import com.corundumstudio.socketio.AuthorizationListener;
import com.corundumstudio.socketio.SocketConfig;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.Transport;
import com.corundumstudio.socketio.annotation.SpringAnnotationScanner;
import com.wa.authory.BackendLoginAuthor;
import com.wa.authory.FrontLoginAuthor;
import com.wa.authory.VisitorLoginAuthor;
import com.wa.constants.UserTypeConstant;
import com.wa.my.util.WebSocketUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;

import javax.annotation.Resource;
import java.util.Objects;

//@Configuration
//@ConfigurationProperties(prefix = "spring.websocket.socketio")
//@ConditionalOnProperty(value = "spring.websocket.enable")
public class WebSocketConfig extends WebSocketCustomerProperties {

    private static final Logger logger = LoggerFactory.getLogger(WebSocketConfig.class);

    @Resource
    private BackendLoginAuthor backendLoginAuthor;

    @Resource
    private FrontLoginAuthor frontLoginAuthor;

    @Resource
    private VisitorLoginAuthor visitorLoginAuthor;

    /**
     * SocketIOServer配置
     *
     * @return
     */
    @Bean(value = "socketIOServer", destroyMethod = "stop")
    public SocketIOServer socketIOServer() {
        return new SocketIOServer(config());
    }

    /**
     * 权限校验
     *
     * @return
     */
    private AuthorizationListener authorizationListener() {
        return data -> {
            //从地址中获取参数  例子：wss://testxqq.allchips.com/ws/?a=3344&b=6090&EIO=3&transport=websocket
            String from = data.getSingleUrlParam("b");
            Integer userType = Convert.toInt(from);
            // 后端用户校验
            if (Objects.equals(userType, UserTypeConstant.BACKEND_USER)) {
                return backendLoginAuthor.authorize(WebSocketUtil.getHttpRequestToken(data.getHttpHeaders().get(WebSocketUtil.COOKIE_HEADER_NAME)));
            }
            // 前端用户校验
            if (Objects.equals(userType, UserTypeConstant.FRONT_USER)) {
                return frontLoginAuthor.authorize("");
            }
            // 游客校验
            if (Objects.equals(userType, UserTypeConstant.VISITOR)) {
                return visitorLoginAuthor.authorize("");
            }
            return false;
        };
    }

    /**
     * config
     *
     * @return
     */
    public com.corundumstudio.socketio.Configuration config() {
        com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();
        // 配置端口
        config.setPort(port);
        // 设置允许源
        config.setOrigin(":*:");
        // 开启Socket端口复用
        SocketConfig socketConfig = new SocketConfig();
//        socketConfig.setReuseAddress(true);
        config.setSocketConfig(socketConfig);
        // 连接数大小
        config.setWorkerThreads(workCount);
        // 允许客户请求
        config.setAllowCustomRequests(allowCustomRequests);
        // 协议升级超时时间(毫秒)，默认10秒，HTTP握手升级为ws协议超时时间
        config.setUpgradeTimeout(upgradeTimeout);
        // Ping消息超时时间(毫秒)，默认60秒，这个时间间隔内没有接收到心跳消息就会发送超时事件
        config.setPingTimeout(pingTimeout);
        // Ping消息间隔(毫秒)，默认25秒。客户端向服务器发送一条心跳消息间隔
        config.setPingInterval(pingInterval);
        // 设置HTTP交互最大内容长度
        config.setMaxHttpContentLength(maxHttpContentLength);
        // 设置最大每帧处理数据的长度，防止他人利用大数据来攻击服务器
        config.setMaxFramePayloadLength(maxFramePayloadLength);
        // 连接认证，这里使用token更合适
        config.setAuthorizationListener(authorizationListener());
        // 连接方式
        config.setTransports(Transport.POLLING, Transport.WEBSOCKET);
        // 域
        config.setContext("/socket.io");
        return config;
    }

    /**
     * 开启SocketIOServer注解支持
     *
     * @return
     */
    @Bean
    public SpringAnnotationScanner springAnnotationScanner() {
        return new SpringAnnotationScanner(socketIOServer());
    }

}
